<!DOCTYPE html>



  


<html class="theme-next muse use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">





  <link rel="alternate" href="/atom.xml" title="renhao" type="application/atom+xml">






<meta name="description" content="仿照qq音乐界面准备写个在线的web music player，理所应当考虑到后台的问题，之前准备用别人封装好的开源库-网易云NODE版API库，但是又有部署之类一系列问题（这样看起来就觉得没什么难度而且还low不方便），就决定自己封装直接请求官方API。">
<meta property="og:type" content="article">
<meta property="og:title" content="跨域问题及解决方法">
<meta property="og:url" content="https://huangrenhao.gitee.io/2019/04/07/browser-cross-domain/index.html">
<meta property="og:site_name" content="renhao">
<meta property="og:description" content="仿照qq音乐界面准备写个在线的web music player，理所应当考虑到后台的问题，之前准备用别人封装好的开源库-网易云NODE版API库，但是又有部署之类一系列问题（这样看起来就觉得没什么难度而且还low不方便），就决定自己封装直接请求官方API。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2020-09-24T03:34:31.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="跨域问题及解决方法">
<meta name="twitter:description" content="仿照qq音乐界面准备写个在线的web music player，理所应当考虑到后台的问题，之前准备用别人封装好的开源库-网易云NODE版API库，但是又有部署之类一系列问题（这样看起来就觉得没什么难度而且还low不方便），就决定自己封装直接请求官方API。">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Muse',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://huangrenhao.gitee.io/2019/04/07/browser-cross-domain/">





  <title>跨域问题及解决方法 | renhao</title>
  








<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">
  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">renhao</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://huangrenhao.gitee.io/2019/04/07/browser-cross-domain/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="renhao">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="renhao">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">跨域问题及解决方法</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-04-07T11:04:22+08:00">
                2019-04-07
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope="" itemtype="http://schema.org/Thing">
                  <a href="/categories/browser/" itemprop="url" rel="index">
                    <span itemprop="name">browser</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2019/04/07/browser-cross-domain/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count valine-comment-count" data-xid="/2019/04/07/browser-cross-domain/" itemprop="commentCount"></span>
                </a>
              </span>
            
          

          
          

          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  3.6k
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  14
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>仿照qq音乐界面准备写个在线的<a href="https://github.com/JackChuChou/web-music-player" target="_blank" rel="noopener">web music player</a>，理所应当考虑到后台的问题，之前准备用别人封装好的开源库-<a href="https://binaryify.github.io/NeteaseCloudMusicApi/#/" target="_blank" rel="noopener">网易云NODE版API库</a>，但是又有部署之类一系列问题（这样看起来就觉得没什么难度而且还low不方便），就决定自己封装直接请求官方API。<a id="more"></a></p>
<h3 id="开始"><a href="#开始" class="headerlink" title="开始"></a>开始</h3><p>在这个项目中无论是直接使用ajax或者是封装好的aixos库直接发起请求都会面临跨域的问题，了解跨域首先要了解一下几个概念：</p>
<ul>
<li><p>同源： 是指相同的协议、域名、端口都相同的才属于同源，使用同源策略除浏览器外还有 cookie、localStorage、IndexDB</p>
</li>
<li><p>同源策略：<strong>浏览器</strong>出于安全考虑，在全局层面禁止了页面加载或执行与自身来源不同域的任何脚本，站外其他来源的脚本页面同页面的交互则被严格限制</p>
</li>
<li><p>CORS：跨域资源共享，使用额外的HTTP头告诉浏览器让运行在一个origin（domain）上的web应用被准许访问来自不同源服务器上的指定的资源</p>
</li>
<li><p>简单请求与预检请求：对于可能对服务器数据产生副作用的HTTP请求方法（特别是GET以外的HTTP请求，或者是搭配某些MIME类型的POST请求），浏览器必须首先使用<strong>OPTIONS</strong>方法发起一个预检请求，从而获知服务端是否允许该实际请求。在预检请求返回中服务器端也可以通知客户端是否需要携带身份凭证（包括Cookies和HTTP认证相关数据）。预检请求的使用可以避免跨域请求对服务器的用户数据产生非预期的影响。</p>
<p>使用到预检请求的条件：使用了除GET、HEAD、POST之外的方法；人为设置了对CORS安全的首部字段集合之外的其他首部字段；Content-Type的值不属于application/x-www-form-urlencoded、multipart/form-data、text/plain之一；等等（详细参见<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS" target="_blank" rel="noopener">MDN</a>）</p>
<p>预检请求报文中的Access-Control-Request-Method首部字段告知服务器实际请求所使用的HTTP方法，Access-Control-Request-Headers首部字段告知服务器实际请求所携带的自定义首部字段。服务器返回的Access-Control-Allow-Methods首部字段将所有允许的请求方法告知客户端（与Allow类似，但只能用于涉及CORS的场景中）。</p>
</li>
</ul>
<p>由同源策略可知，跨域是由于浏览器的缘故，凡是发送请求的URL的协议、域名、端口任意一个与当前页面的地址不同都视为跨域。所以说其实跨域的问题并非都是浏览器限制发起跨域请求，而也有的是在服务端返回请求后浏览器会阻止非同源数据。</p>
<h3 id="跨域限制的原因"><a href="#跨域限制的原因" class="headerlink" title="跨域限制的原因"></a>跨域限制的原因</h3><p>当然是出于安全考虑</p>
<p>ajax同源策略只要用来防止CSRF（Cross-site request forgery，跨站请求伪造）攻击，没有ajax同源策略我们发起的每一次HTTP请求都会带上请求地址对应的cookie，那么可以做如下攻击：</p>
<ol>
<li>用户登录了自己的银行页面<code>http://mybank.com</code>，<code>http://mybank.com</code>向用户的cookie中添加用户标识。</li>
<li>用户浏览了恶意页面 <code>http://evil.com</code>。执行了页面中的恶意AJAX请求代码。</li>
<li><code>http://evil.com</code>向<code>http://mybank.com</code>发起AJAX HTTP请求，请求会默认把<code>http://mybank.com</code>对应cookie也同时发送过去。</li>
<li>银行页面从发送的cookie中提取用户标识，验证用户无误，response中返回请求数据。此时数据就泄露了。</li>
<li>而且由于Ajax在后台执行，用户无法感知这一过程。</li>
</ol>
<blockquote>
<p>Cookie: 是浏览器访问服务器后，服务器传给浏览器的一段数据。浏览器需要保存这段数据，不会轻易删除。此后每次浏览器访问该服务器，都必须带上这段数据。</p>
<p>Cookie 一般有两个作用：识别用户身份和记录历史。</p>
</blockquote>
<h3 id="跨域问题的解决方案"><a href="#跨域问题的解决方案" class="headerlink" title="跨域问题的解决方案"></a>跨域问题的解决方案</h3><h4 id="前端："><a href="#前端：" class="headerlink" title="前端："></a>前端：</h4><ol>
<li><p>JSONP</p>
<p><code>&lt;script&gt;</code>标签是不受同源策略的限制的，它可以载入任意地方的 JavaScript 文件，而并不要求同源。</p>
<p>所以 JSONP 的理念就是，我和服务端约定好一个函数名，当我请求文件的时候，服务端返回一段 JavaScript。这段 JavaScript 调用了我们约定好的函数，并且将数据当做参数传入。非常巧合的一点（其实并不是），JSON 的数据格式和 JavaScript 语言里对象的格式正好相同。所以在我们约定的函数里面可以直接使用这个对象。</p>
<p>缺点：</p>
<ul>
<li><strong>只能通过GET方式请求，一方面是参数长度有限制，二是安全性比较差</strong>；</li>
<li><strong>后端需要知道前端的cb是什么样的结构</strong>，主要在参数和回调名；</li>
<li>后端需要进行参数和cb的拼接然后才能执行；</li>
</ul>
<p>使用方式：</p>
<ul>
<li><p>前端请求页面</p>
<pre><code>// 定义一个fun函数
function fun(fata) {
    console.log(data);
};
// 创建一个脚本，并且告诉后端回调函数名叫fun
var body = document.getElementsByTagName(&#39;body&#39;)[0];
var script = document.getElement(&#39;script&#39;);
script.type = &#39;text/javasctipt&#39;;
script.src = &#39;demo.js?callback=fun&#39;;
body.appendChild(script);
</code></pre></li>
<li><p>demo.js</p>
<pre><code>fun({&quot;name&quot;:&quot;name&quot;})
</code></pre><p>这里的fun是事先定义好的，在实际情况下需要动态的创建这个fun函数，然后在数据返回的时候销毁它。</p>
</li>
</ul>
<p><strong>jsonp 为什么用 script 标签，而不是 img、link 标签？</strong></p>
<ul>
<li>img 需要后端返回一个真正的图片，如果不是会被浏览器识别出来，就不能执行 image.onload ，而是执行 image.onerror，动态 img 可以不放入页面就能发起请求，而 script 必须放入页面，在页面中放入一个 script ，那么里面的内容就会执行，所以可以不用监听 script.onload，可以在后端返回的 script 中写入要执行的代码。</li>
</ul>
<blockquote>
<p>还是看不懂就看<a href="https://blog.csdn.net/hansexploration/article/details/80314948" target="_blank" rel="noopener">这里</a></p>
</blockquote>
</li>
<li><p>document.domain+iframe</p>
<ul>
<li>关键点<ul>
<li>跨域分为两种，一种xhr（XMLHttpRequest，ajax功能实现依赖的对象）不能访问不同源的文档，另一种是不同window之间不能进行交互操作;</li>
<li><code>document.domain</code>主要是解决第二种情况，且只能适用于主域相同子域不同的情况；</li>
<li><code>document.domain</code>的设置是有限制的，<strong>我们只能把</strong><code>document.domain</code><strong>设置成自身或更高一级的父域</strong>，<strong>且主域必须相同</strong>。例如：<code>a.b.example.com</code>中某个文档的<code>document.domain</code>可以设成<code>a.b.example.com、b.example.com 、example.com</code>中的任意一个，但是不可以设成<code>c.a.b.example.com</code>，因为这是当前域的子域，也不可以设成baidu.com，因为主域已经不相同了。</li>
</ul>
</li>
<li>兼容性：所有浏览器都支持；</li>
<li><p>优点：</p>
<ul>
<li>可以实现不同window之间的相互访问和操作；</li>
</ul>
</li>
<li>缺点：<ul>
<li>只适用于父子window之间的通信，不能用于xhr；</li>
<li>只能在主域相同且子域不同的情况下使用；</li>
</ul>
</li>
<li><p>使用方式</p>
<ul>
<li><p>在<code>www.a.com/a.html</code>中：</p>
<pre><code>document.domain = &#39;a.com&#39;;
var ifr = document.createElement(&#39;iframe&#39;);
ifr.src = &#39;http://www.script.a.com/b.html&#39;;
ifr.display = none;
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
//在这里操作doc，也就是b.html
ifr.onload = null;
};
</code></pre></li>
<li><p>在<code>www.script.a.com/b.html</code>中：</p>
<p><code>document.domain = &#39;a.com&#39;</code></p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>window.name</p>
<ul>
<li><p>关键点：window.name在页面的生命周期里共享一个window.name;</p>
</li>
<li><p>兼容性：所有浏览器都支持；</p>
</li>
<li><p>优点：</p>
<ul>
<li>最简单的利用了浏览器的特性来做到不同域之间的数据传递；</li>
<li>不需要前端和后端的特殊配制；</li>
</ul>
</li>
<li><p>缺点：</p>
<ul>
<li>大小限制：window.name最大size是2M左右，不同浏览器中会有不同约定；</li>
<li>安全性：当前页面所有window都可以修改，很不安全；</li>
<li>数据类型：传递数据只能限于字符串，如果是对象或者其他会自动被转化为字符串</li>
</ul>
</li>
<li><p>使用方式：</p>
<ul>
<li><p>创建<code>a.com/cs1.html</code></p>
</li>
<li><p>创建<code>a.com/proxy.html</code>，代码如下：</p>
<pre class=" language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
 <span class="token keyword">function</span> <span class="token function">proxy</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> func<span class="token punctuation">)</span><span class="token punctuation">{</span>
 <span class="token keyword">var</span> isFirst <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  ifr <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'iframe'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  loadFunc <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
   <span class="token keyword">if</span><span class="token punctuation">(</span>isFirst<span class="token punctuation">)</span><span class="token punctuation">{</span>
       ifr<span class="token punctuation">.</span>contentWindow<span class="token punctuation">.</span>location <span class="token operator">=</span> <span class="token string">'http://a.com/cs1.html'</span><span class="token punctuation">;</span>
       isFirst <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span>
       <span class="token function">func</span><span class="token punctuation">(</span>ifr<span class="token punctuation">.</span>contentWindow<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
       ifr<span class="token punctuation">.</span>contentWindow<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>ifr<span class="token punctuation">)</span><span class="token punctuation">;</span>
       ifr<span class="token punctuation">.</span>src <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
       ifr <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

 ifr<span class="token punctuation">.</span>src <span class="token operator">=</span> url<span class="token punctuation">;</span>
 ifr<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'none'</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span><span class="token punctuation">(</span>ifr<span class="token punctuation">.</span>attachEvent<span class="token punctuation">)</span> ifr<span class="token punctuation">.</span><span class="token function">attachEvent</span><span class="token punctuation">(</span><span class="token string">'onload'</span><span class="token punctuation">,</span> loadFunc<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">else</span> ifr<span class="token punctuation">.</span>onload <span class="token operator">=</span> loadFunc<span class="token punctuation">;</span>

 document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>ifr<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
 <span class="token function">proxy</span><span class="token punctuation">(</span><span class="token string">'http://b.com/cs1.html'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span>
</code></pre>
</li>
<li><p>在<code>b.com/cs1.html</code>中包含：</p>
<pre><code>&lt;script&gt;
 window.name = &#39;要传送的内容&#39;;
&lt;/script&gt;
</code></pre></li>
</ul>
</li>
</ul>
</li>
<li><p>postMessage</p>
<ul>
<li><p>关键点：postMessage是h5引入的一个新概念，现在也在进一步的推广和发展中，他进行了一系列的封装，我们可以通过window.postMessage的方式进行使用，并可以监听其发送的消息；</p>
</li>
<li><p>优点</p>
<ul>
<li>不需要后端介入就可以非常简单的的做到跨域，一个函数外加两个参数（请求url，发送数据）就可以搞定；</li>
<li>移动端兼容性好；</li>
</ul>
</li>
<li><p>缺点</p>
<ul>
<li>无法做到一对一的传递方式：监听中需要做很多消息的识别，由于postMessage发出的消息对于同一个页面的不同功能相当于一个广播的过程，该页面的所有onmessage都会收到，所以需要做消息的判断；</li>
<li>安全性问题：三方可以通过截获，注入html或者脚本的形式监听到消息，从而能够做到篡改的效果，所以在postMessage和onmessage中一定要做好这方面的限制；</li>
<li>发送的数据会通过<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm" target="_blank" rel="noopener">结构化克隆算法</a>进行序列化，所以只有满足该算法要求的参数才能够被解析，否则会报错，如function就不能当作参数进行传递；</li>
</ul>
</li>
<li><p>使用方法：</p>
<p>1) a.com/index.html中的代码：</p>
<pre><code>&lt;iframe id=&quot;ifr&quot; src=&quot;b.com/index.html&quot;&gt;&lt;/iframe&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
window.onload = function() {
 var ifr = document.getElementById(&#39;ifr&#39;);
 var targetOrigin = &#39;http://b.com&#39;; // 若写成&#39;http://b.com/c/proxy.html&#39;效果一样
          // 若写成&#39;http://c.com&#39;就不会执行postMessage了
 ifr.contentWindow.postMessage(&#39;I was there!&#39;, targetOrigin);
};
&lt;/script&gt;
</code></pre><p>2) b.com/index.html中的代码：</p>
<pre><code>&lt;script type=&quot;text/javascript&quot;&gt;
 window.addEventListener(&#39;message&#39;, function(event){
  // 通过origin属性判断消息来源地址
  if (event.origin == &#39;http://a.com&#39;) {
   alert(event.data); // 弹出&quot;I was there!&quot;
   alert(event.source); // 对a.com、index.html中window对象的引用
         // 但由于同源策略，这里event.source不可以访问window对象
  }
 }, false);
&lt;/script&gt;
</code></pre></li>
</ul>
</li>
</ol>
<p><a href="https://www.jb51.net/article/97611.htm" target="_blank" rel="noopener">参考</a></p>
<h4 id="服务器："><a href="#服务器：" class="headerlink" title="服务器："></a>服务器：</h4><ol>
<li><p>cors</p>
<p>CORS是一个W3C标准，全称是”跨域资源共享”（Cross-origin resource sharing）。 对于这个方式，阮一峰老师总结的<a href="http://www.ruanyifeng.com/blog/2016/04/cors.html" target="_blank" rel="noopener">文章</a>特别好。</p>
<p>浏览器将 cors 请求分成两类：<strong>简单请求</strong>和<strong>非简单请求</strong>。简单请求满足：</p>
<ul>
<li><strong>请求方法是 HEAD、GET、POST</strong></li>
<li><strong>HTTP 头信息不超过：Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type</strong>（只限于<code>application/x-www-form-urlencoded</code>、<code>multipart/form-data</code>、<code>text/plain</code>）</li>
</ul>
<p><strong>对于简单请求</strong>，直接发出 cors 请求，即在头信息之中增加一个 origin（用来说明此次请求来自哪个源，如果 origin 指定的域名在服务器许可范围内，服务器返回的响应就会多出几个头信息字段（以 Access-Control- 开头），没有包含这些字段浏览器就会得知出错。</p>
<p><strong>对于非简单请求</strong>，正式通信之前会增加预检请求，浏览器会询问服务器当前网页所在域名是否在服务器的许可名单中以及可以使用哪些 HTTP 方法和头信息字段</p>
<p>注意：</p>
<ol>
<li><p>对于客户端，我们还是正常使用xhr对象发送ajax请求。<br>唯一需要注意的是，我们需要设置我们的xhr属性<strong>withCredentials</strong>为true，否则cookie带不过去，设置<code>xhr.withCredentials = true</code>;</p>
</li>
<li><p>对于服务器端，需要在 response header中设置如下两个字段:</p>
<pre><code>// 指定该响应的资源是否允许与给定的origin共享
Access-Control-Allow-Origin: http://www.yourhost.com

// 表示是否可以将对请求的响应暴露给页面，返回true则可以，其他值均不可以
// credentials可以是cookies,authorization headers,TLS client certificates
// 是否允许客户端携带验证信息
Access-Control-Allow-Credentials:true
</code></pre><blockquote>
<p>设置 header</p>
<ul>
<li><p>node：</p>
<ul>
<li><p>response.writeHeader(200, {‘Content-Type’: ‘text/plain’})</p>
</li>
<li><p>response.setHeader(‘Set-Cookie’, [‘type=xx’, ‘language=xx’])</p>
<p>writeHeader 优先级更高，setHeader 会与 writeHeader 进行合并。writeHeader 不会在内部进行缓存，直接写入网络通道，getHeader 获取不到</p>
<blockquote>
<p><a href="http://nodejs.cn/api/http.html#http_response_setheader_name_value" target="_blank" rel="noopener">参考</a></p>
</blockquote>
</li>
</ul>
</li>
<li><p>koa：</p>
<ul>
<li>设置响应头：ctx.set(‘Content-Type’: ‘application/json’)</li>
<li>添加请求头ctx.append(‘Referer’, ‘<a href="http://xxx&#39;" target="_blank" rel="noopener">http://xxx&#39;</a>)</li>
</ul>
</li>
</ul>
</blockquote>
</li>
<li><p>100个非简单请求/预检，能不能加速？答：优化OPTIONS预检请求的发送，CORS中 Access-Control-Max-age 可以设置缓存的时间，表示多少秒内不会对同一个非简单请求去发送预检请求，这样的话就能够减少重复多次发送options请求的往返时间</p>
</li>
</ol>
</li>
<li><p>代理</p>
<p>浏览器有跨域限制，但是服务器不存在跨域问题，所以可以由服务器请求所要域的资源再返回给客户端。</p>
<h4 id="可以利用-nginx-反向代理解决跨域问题："><a href="#可以利用-nginx-反向代理解决跨域问题：" class="headerlink" title="可以利用 nginx 反向代理解决跨域问题："></a>可以利用 nginx 反向代理解决跨域问题：</h4><blockquote>
<p>反向代理隐藏了真实的服务端，如请求 <code>www.baidu.com</code>，<code>www.baidu.com</code>就是反向代理服务器，反向代理服务器会帮我们把请求转发到真实的服务器哪里去，反向代理常用来做负载均衡。</p>
<p>正向代理隐藏了真实的客户端，如翻墙工具 vpn。</p>
</blockquote>
<p>nginx 设置反向代理：<code>proxy_pass</code> 。</p>
<ul>
<li>当网站前端代码和后端代码放在同一个服务端口和目录下，则不存在跨域，前端直接访问第三方 api 改为用后端访问，用后端做个中间人将得到的数据返回给前端。</li>
<li>前端网站采用 nginx 配置，nginx 中用 <code>proxy_pass</code> 设置反向代理，将特定请求 api 转到第三方 api，当浏览器访问 nginx 服务地址时 nginx 做了转换，实际上访问的是第三方 api 地址。</li>
</ul>
<p>使用 nginx 可以解决生产环境下跨域的配置问题，开发环境下可以使用 webpack 本地开发插件 webpack-dev-server 中 devServer 的 proxy 属性设置（webpack-dev-server 使用 http-proxy-middleware 实现跨域代理）</p>
</li>
</ol>
<h3 id="网易云NODE版API库"><a href="#网易云NODE版API库" class="headerlink" title="网易云NODE版API库"></a>网易云NODE版API库</h3><p>按照介绍主要用到的技术有<code>跨站请求伪造 (CSRF)</code>, <code>伪造请求头</code> , <code>调用官方 API</code>，</p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/04/05/browser-a-biao-qian-zhong-de-rel-noopener/" rel="next" title="HTML标签中的非常用属性">
                <i class="fa fa-chevron-left"></i> HTML标签中的非常用属性
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/04/09/vue-virtual-dom/" rel="prev" title="Vue react 中的虚拟DOM和diff">
                Vue react 中的虚拟DOM和diff <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
    </div>
  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">renhao</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">94</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">19</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#开始"><span class="nav-number">1.</span> <span class="nav-text">开始</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#跨域限制的原因"><span class="nav-number">2.</span> <span class="nav-text">跨域限制的原因</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#跨域问题的解决方案"><span class="nav-number">3.</span> <span class="nav-text">跨域问题的解决方案</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#前端："><span class="nav-number">3.1.</span> <span class="nav-text">前端：</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#服务器："><span class="nav-number">3.2.</span> <span class="nav-text">服务器：</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#可以利用-nginx-反向代理解决跨域问题："><span class="nav-number">3.3.</span> <span class="nav-text">可以利用 nginx 反向代理解决跨域问题：</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#网易云NODE版API库"><span class="nav-number">4.</span> <span class="nav-text">网易云NODE版API库</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">renhao</span>

  
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    
      <span class="post-meta-item-text">Site words total count&#58;</span>
    
    <span title="Site words total count">265.9k</span>
  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Muse</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  










  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src="//unpkg.com/valine/dist/Valine.min.js"></script>
  
  <script type="text/javascript">
    var GUEST = ['nick','mail','link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item=>{
      return GUEST.indexOf(item)>-1;
    });
    new Valine({
        el: '#comments' ,
        verify: false,
        notify: false,
        appId: '2P1xqUWiCoNm14MH4yhURlJi-gzGzoHsz',
        appKey: 'uJN0uagHIVgXtBO1OuLV9Ban',
        placeholder: 'Just go go',
        avatar:'mm',
        guest_info:guest,
        pageSize:'10' || 10,
    });
  </script>



  





  

  

  

  
  

  

  

  

</body>
</html>
